home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr22 / dtkclk11.zip / READ.C < prev    next >
Text File  |  1993-05-05  |  5KB  |  169 lines

  1. /*
  2.  * Routines to read the DTK clock/calendar board.
  3.  * (C) Copyright 1989 Richard B. Wales.  All Rights Reserved.
  4.  */
  5.  
  6. #include "clkdefs.h"
  7.  
  8.  
  9. /*
  10.  * READ_CLOCK
  11.  *    Reads the date/time from the clock board.
  12.  *    An additional "tens of seconds" offset is derived from the "day
  13.  *    of the week" value on the clock board (by comparing this value
  14.  *    with the true day of the week), and is added into the returned
  15.  *    value.
  16.  */
  17. struct clockval *
  18. read_clock (void)
  19. {    unsigned char clkdata[13];
  20.     unsigned char save_seconds;
  21.     int n, tries, wkday;
  22.     static struct clockval cval;
  23.  
  24.     /*
  25.      * Prepare to read data from the clock.
  26.      */
  27.     outportb (PPICTRL, PPI_READ);        /* ready to read from PPI */
  28.     outportb (CLKCTRL, 0);            /* clear clock control bits */
  29.  
  30.     /*
  31.      * Verify that the clock is actually there by writing an arbitrary
  32.      * value to the PPI's port B, and then trying to read it back.
  33.      * This test really only verifies that something resembling a PPI
  34.      * is active in the I/O port address space used by the DTK clock.
  35.      */
  36.     outportb (CLKADDR, 0x55);
  37.     if (inportb (CLKADDR) != 0x55) return NULL_CLOCK;
  38.  
  39.     /*
  40.      * Read the clock value, starting with the seconds.
  41.      * After reading the entire clock, read the seconds digit again;
  42.      * if it has changed from the initial reading,
  43.      * read the entire clock value again.
  44.      */
  45.     tries = 4;
  46.     READY_TO_READ;
  47.     do
  48.     {    for (n = 0; n < 13; n++) READ_CLOCK (n);
  49.         save_seconds = clkdata[0]; READ_CLOCK (0);
  50.     } while (--tries > 0 && clkdata[0] != save_seconds);
  51.     DONE_READING;
  52.     if (clkdata[0] != save_seconds) return NULL_CLOCK;
  53.  
  54.     /*
  55.      * Check for 12- or 24-hour mode.
  56.      * If the clock value is in 12-hour mode,
  57.      * transform to 24-hour mode before proceeding further.
  58.      */
  59.     switch (clkdata[5] & 0xc)
  60.     {    case 0x0:            /* 12-hour AM */
  61.             if (clkdata[5] == 1 && clkdata[4] == 2)
  62.                 clkdata[5] = 0, clkdata[4] = 0;
  63.             break;
  64.         case 0x4:            /* 12-hour PM */
  65.             clkdata[5] &= 0x3;
  66.             if (clkdata[5] != 1 || clkdata[4] != 2)
  67.             {    clkdata[5] += 1, clkdata[4] += 2;
  68.                 if (clkdata[4] >= 10)
  69.                     clkdata[4] -= 10, clkdata[5] += 1;
  70.             }
  71.             break;
  72.         default:            /* 24-hour */
  73.             clkdata[5] &= 0x3;
  74.     }
  75.  
  76.     /*
  77.      * The 4-bit of the "tens of days" digit is used as a leap-year
  78.      * indicator (current or coming February will have 29 days).
  79.      * This information is not important while reading the clock.
  80.      */
  81.     clkdata[8] &= 0x3;
  82.  
  83.     /*
  84.      * Copy the clock data into the output structure (BCD format).
  85.      * Note that the "century" information is not included in the
  86.      * clock output, and must be generated by the program on the
  87.      * assumption that the year is in the range 1980 through 2079.
  88.      */
  89.     cval.cv_second  = clkdata[1] * 10 + clkdata[0];
  90.     cval.cv_minute  = clkdata[3] * 10 + clkdata[2];
  91.     cval.cv_hour    = clkdata[5] * 10 + clkdata[4];
  92.     cval.cv_day     = clkdata[8] * 10 + clkdata[7];
  93.     cval.cv_month   = clkdata[10] * 10 + clkdata[9];
  94.     cval.cv_year    = clkdata[12] * 10 + clkdata[11];
  95.     cval.cv_century = ((clkdata[12] >= 8) ? 19 : 20);
  96.  
  97.     /*
  98.      * Perform a few simple sanity checks on the result.
  99.      */
  100.     if (cval.cv_month == 0 || cval.cv_month > 12
  101.         || cval.cv_day == 0 || cval.cv_day > 31
  102.         || cval.cv_hour >= 24
  103.         || cval.cv_minute >= 60
  104.         || cval.cv_second >= 60)
  105.         return NULL_CLOCK;
  106.  
  107.     /*
  108.      * Since a major design misfeature of the 5832 chip causes the
  109.      * "seconds" to be reset to zero whenever a new time is written
  110.      * to the clock, the "day of the week" on the clock encodes an
  111.      * additional multiple of ten seconds to be added to the clock
  112.      * value.  Extract this quantity by comparing the clock data
  113.      * with the true day of the week, then adjust the time accordingly.
  114.      */
  115.     wkday = clkdata[6] - day_of_the_week (&cval);
  116.     while (wkday < 0) wkday += 7;
  117.     while (wkday >= 7) wkday -= 7;
  118.     advance_time (&cval, 10 * wkday);
  119.  
  120.     /*
  121.      * Return the clock value to the calling routine.
  122.      */
  123.     return &cval;
  124. }
  125.  
  126.  
  127. /*
  128.  * CLOCK_TO_TIME
  129.  *    Converts the unified date/time structure used by the bulk of
  130.  *    the program into the separate "date" and "time" structures
  131.  *    used by DOS.
  132.  */
  133. void
  134. clock_to_time (struct clockval *cv,
  135.            struct date **da,
  136.            struct time **ti)
  137. {    static struct date date;
  138.     static struct time time;
  139.  
  140.     /*
  141.      * Perform sanity checking on the input parameters.
  142.      */
  143.     if (da != NULL_DATE_P) *da = NULL_DATE;
  144.     if (ti != NULL_TIME_P) *ti = NULL_TIME;
  145.     if (cv == NULL_CLOCK || da == NULL_DATE_P || ti == NULL_TIME_P)
  146.         return;
  147.  
  148.     /*
  149.      * Set up the date structure.
  150.      */
  151.     date.da_year    = cv->cv_century * 100 + cv->cv_year;
  152.     date.da_mon    = cv->cv_month;
  153.     date.da_day    = cv->cv_day;
  154.  
  155.     /*
  156.      * Set up the time structure.
  157.      */
  158.     time.ti_hour    = cv->cv_hour;
  159.     time.ti_min    = cv->cv_minute;
  160.     time.ti_sec    = cv->cv_second;
  161.     time.ti_hund    = 0;
  162.  
  163.     /*
  164.      * Set the returned values.
  165.      */
  166.     *da = &date;
  167.     *ti = &time;
  168. }
  169.